/**
 *Copyright (c) 2024 watereyes
 * workflow is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.workflow.common.util;


import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

import org.springframework.util.Assert;

public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
	
	private static String[] MONTHS = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};

	private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
			"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss",
			"yyyy.MM.dd HH:mm", "yyyy.MM" };
	
	private static final String[][] WEEK = {{"MONDAY", "一"}, {"TUESDAY", "二"}, {"WEDNESDAY", "三"}, {"THURSDAY", "四"}, {"FRIDAY", "五"}, {"SATURDAY", "六"}, {"SUNDAY", "日"}};

	public static String monthUS(int index) {
		return MONTHS[index];
	}

	public static Date getDate() {
		return new Date();
	}

	public static final ThreadLocal<Date> date = new ThreadLocal<Date>() {
		protected Date initialValue() {
			return new Date();
		}
	};

	public static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd");
		}
	};

	public static int getYear() {
		Calendar calendar = Calendar.getInstance();
		return calendar.get(Calendar.YEAR);
	}

	public static int getMonth() {
		Calendar calendar = Calendar.getInstance();
		return calendar.get(Calendar.MONTH);
	}

	public static int getDay() {
		Calendar calendar = Calendar.getInstance();
		return calendar.get(Calendar.DAY_OF_MONTH);
	}

	public static String parseDate(Date date, String pattern) {
		Assert.notNull(date, "date must not be null");
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	public static Date parseDate(String date) {
		Assert.notNull(date, "date must not be null");
		try {
			return parseDate(date, parsePatterns);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
    public static String getWeek() {
    	LocalDate date = LocalDate.now();
    	String week = String.valueOf(date.getDayOfWeek());
    	for(int i = 0; i < WEEK.length; i++) {
    		if(Objects.equals(week, WEEK[i][0])) {
    			return "星期" + WEEK[i][1];
    		}
    	}
    	return week;
    }
    
    /**
     * 天数间隔
     * @param beginDate
     * @param endDate
     * @return
     */
    public static int betweenDays(Date beginDate, Date endDate) {
    	LocalDate blocal = toLocalDate(beginDate);
    	LocalDate elocal = toLocalDate(endDate);
    	return (int) Math.abs(ChronoUnit.DAYS.between(blocal, elocal));
    }
    
    /**
     * 月份间隔
     * @param beginDate
     * @param endDate
     * @return
     */
    public static int betweenMonths(Date beginDate, Date endDate) {
    	LocalDate blocal = toLocalDate(beginDate);
    	LocalDate elocal = toLocalDate(endDate);
    	return (int) Math.abs(ChronoUnit.MONTHS.between(blocal, elocal));
    }
    
    /**
     * 年份间隔
     * @param beginDate
     * @param endDate
     * @return
     */
    public static int betweenYears(Date beginDate, Date endDate) {
    	LocalDate blocal = toLocalDate(beginDate);
    	LocalDate elocal = toLocalDate(endDate);
    	return (int) Math.abs(ChronoUnit.YEARS.between(blocal, elocal));
    }
    
    public static LocalDate toLocalDate(Date date) {
    	Instant instant = date.toInstant();
    	ZoneId zone = ZoneId.systemDefault();
    	LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
    	return localDateTime.toLocalDate();
    }

	public static int getMonthId() {
		LocalDate date = LocalDate.now();
		String monthId = date.format(DateTimeFormatter.ofPattern("yyyyMM"));
		return Integer.parseInt(monthId);
	}
	
	public static int getMonthId(long monthsToSubtract) {
		LocalDate date = LocalDate.now();
		String monthId = date.plusMonths(monthsToSubtract)
				.format(DateTimeFormatter.ofPattern("yyyyMM"));
		return Integer.parseInt(monthId);
	}
	
	public static int getMonthId(int monthId, long monthsToSubtract) {
		String text = String.valueOf(monthId).substring(0, 4) + "-" + String.valueOf(monthId).substring(4, 6) + "-01";
		LocalDate date = LocalDate.parse(text);
		String month = date.plusMonths(monthsToSubtract)
				.format(DateTimeFormatter.ofPattern("yyyyMM"));
		return Integer.parseInt(month);
	}
	
	public static void main(String[] args) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		System.out.println(betweenDays(sdf.parse("2019-09-06"), sdf.parse("2019-09-01")));;
	}
}